# main.py
import time
from pynput import keyboard
from threading import Event
from utils import move_and_click, set_stop_event, move_relative, save_log, check_color, press_key
from read import read_hand
from option import find_fa, find_wan, find_han
from package import get_gold_index, get_is_win
from settings import sleep_options
from mail import send_notification_email

# 用于控制脚本是否继续运行的事件，定义为全局变量
stop_event = Event()

# 将 stop_event 传递给 utils.py
set_stop_event(stop_event)

def on_press(key):
    global stop_event
    try:
        if key.char == 'q':  # 当按下 'q' 键时
            stop_event.set()
            save_log("你按下了 'q' 键，脚本将停止运行。")
            return False  # 停止监听
    except AttributeError:
        pass


def exchange_cards():
    """
    13面换牌 循环5次
    """
    move_relative(0, -150)
    for _ in range(5):
        # 读取手牌信息，得到手牌数组
        hand_cards = read_hand(region_name="手牌区")
        # 用于记录已经出现过的牌的数字
        seen_cards = set()
        # 用于标记是否进行了换牌操作
        has_exchanged = False
        # 遍历手牌数组
        for index, card in enumerate(hand_cards):
            # 如果当前手牌的值为 0 或者该数字已经出现过，需要换牌
            if card == 0 or card in seen_cards:
                # 构造需要点击的手牌名称，例如 "手牌1"、"手牌2" 等
                card_name = f"手牌{index + 1}"
                # 调用 move_and_click 函数进行换牌操作
                move_and_click(card_name, 0)
                has_exchanged = True  # 标记为已换牌
            else:
                # 将当前牌的数字添加到已出现集合中
                seen_cards.add(card)
        if has_exchanged:
            move_and_click("换牌")
        else:
            move_and_click("跳过")


def play_cards():
    """
    13面打牌 循环36次
    """
    time.sleep(sleep_options["默认移动点击"])
    for i in range(35):
        # 读取手牌信息，得到手牌数组
        hand_cards = read_hand(region_name="手牌区带模切")
        # 用于记录已经出现过的牌的数字
        seen_cards = set()
        # 用于标记是否进行了换牌操作
        has_played = False
        # 遍历手牌数组
        for index, card in enumerate(hand_cards):
            if index == 13:
                continue
            # 如果当前手牌的值为 0 或者该数字已经出现过，需要打出
            if card == 0 or card in seen_cards:
                # 构造需要点击的手牌名称，例如 "手牌1"、"手牌2" 等
                card_name = f"手牌{index + 1}"
                # 调用 move_and_click 函数进行换牌操作
                move_and_click(card_name, 0)
                move_relative(0, -150)
                has_played = True  # 标记为已换牌
                break
            else:
                # 将当前牌的数字添加到已出现集合中
                seen_cards.add(card)
        if not has_played:
            # 如果没有牌可以打，说明已经听牌了，检测模切区
            last_card = hand_cards[-1]
            if last_card == 0:
                move_and_click("模切", 0)
                move_relative(0, -150)
            else:
                move_and_click("和了")
                move_and_click("返回", sleep_options["和牌疯狂点返回"])
                move_and_click("弹框确认", sleep_options["和牌疯狂点返回"])
                move_and_click("继续游戏", sleep_options["继续游戏"])
                return 1
    return 0

def exchange_cards_chelun():
    """
    车轮换牌 循环5次
    """
    move_relative(0, -150)
    for _ in range(5):
        # 读取手牌信息，得到手牌数组
        hand_cards = read_hand(region_name="手牌区", is_chelun=True)
        # 用于记录每张牌出现的次数
        card_count = {}
        # 用于标记是否进行了换牌操作
        has_exchanged = False
        # 遍历手牌数组，判断是否需要换牌
        for index, card in enumerate(hand_cards):
            # 统计当前牌出现的次数
            if card in card_count:
                card_count[card] += 1
            else:
                card_count[card] = 1
            # 如果当前手牌的值为 0 或者该数字已经出现过 4 次及以上，需要换牌
            if card == 0 or card_count[card] > 3:
                # 构造需要点击的手牌名称，例如 "手牌1"、"手牌2" 等
                card_name = f"手牌{index + 1}"
                # 调用 move_and_click 函数进行换牌操作
                move_and_click(card_name, 0)
                has_exchanged = True  # 标记为已换牌
        if has_exchanged:
            move_and_click("换牌")
        else:
            move_and_click("跳过")


def play_cards_chelun():
    """
    车轮打牌 循环36次
    """
    # 用于标记是否听牌
    time.sleep(sleep_options["默认移动点击"])
    has_ting = False
    for i in range(35):
        # 如果没听，需要读牌出牌
        if not has_ting:
            # 读取手牌信息，得到手牌数组
            hand_cards = read_hand(region_name="手牌区", is_chelun=True)
            # 用于记录每张牌出现的次数
            card_count = {}
            # 用于标记是否进行了出牌操作
            has_played = False
            # 遍历手牌数组，统计每张牌出现的次数
            for card in hand_cards:
                if card in card_count:
                    card_count[card] += 1
                else:
                    card_count[card] = 1
            # 再次遍历手牌数组，判断是否需要出牌
            for index, card in enumerate(hand_cards):
                if index == 13:
                    continue
                # 如果当前手牌的值为 0 或者该数字已经出现过 4 次，需要出牌
                if card == 0 or card_count[card] >= 4:
                    # 构造需要点击的手牌名称，例如 "手牌1"、"手牌2" 等
                    card_name = f"手牌{index + 1}"
                    # 调用 move_and_click 函数进行出牌操作
                    move_and_click(card_name, 0)
                    move_relative(0, -150)
                    has_played = True  # 标记为已出牌
                    break
            if not has_played:
                has_ting = True
        # 如果听牌，判断是否自摸胡牌
        if has_ting:
            is_win = get_is_win()
            if not is_win:
                move_and_click("模切", 0)
                move_relative(0, -150)
            else:
                move_and_click("和了")
                move_and_click("返回", sleep_options["和牌疯狂点返回"])
                move_and_click("弹框确认", sleep_options["和牌疯狂点返回"])
                move_and_click("继续游戏", sleep_options["继续游戏"])
                return 1
    return 0

def find_wanxiang(initial_item):
    """
    开包 循环10次
    """
    time.sleep(sleep_options["开包循环"])
    # 定义数组用于记录已有护符
    opened_items = [initial_item]

    for _ in range(30):
        gold_array = get_gold_index()
        is_sell = False
        for gold_index in gold_array:
            button_name1 = f"第{gold_index}个包"
            button_name2 = f"第{gold_index}个包开启"
            move_and_click(button_name1)
            is_money = check_color(button_name2, (246, 215, 113), sleep_options["默认移动点击"])
            if not is_money:
                # 开包没钱卖卡，根据优先级卖，没卡可卖返回0
                is_sell = sell_one(opened_items, button_name1)
                if is_sell:
                    break
                else:
                    return 0
            save_log("开金包")
            move_and_click(button_name2)
            time.sleep(sleep_options["找万象"])
            wan_index, name = find_wan()
            if name == "wan":
                return 1
#             elif name == "gaizao":
#                 return 1
#             elif name == "zai_zi":
#                 return 1
            elif wan_index == -1:
                return 0
            else:
                if name is None:
                    option_name = f"里面的第{wan_index}个选择"
                    move_and_click(option_name, 0)
                    move_and_click("最右边护符", sleep_options["最右边护符"])
                    move_and_click("出售")
                else:
                    save_log(f"找到{name}")
                    if name == "han_p":
                        # 邀请函+ 直接选，选完检测万象
                        option_name = f"里面的第{wan_index}个选择"
                        move_and_click(option_name, 0)
                        opened_items.remove("han")
                        move_and_click("最右边护符", sleep_options["开包循环"])
                        han_name, _ = find_han()
                        save_log(f"plus升级邀请函{han_name}")
                        if han_name is None or han_name in ["dashi", "libao", "suo"]:
                            move_and_click("出售")
                        elif han_name == "wan":
                            return 1
                        else:
                            opened_items.append(han_name)
                            move_and_click("关闭")
                    elif name in ["han", "baiye", "tianen", "mojing", "faming", "youtong", "baozhu"]:
                        option_name = f"里面的第{wan_index}个选择"
                        move_and_click(option_name, 0)
                        opened_items.append(name)
                        # 选完检查已有护符，如果同时有函和白夜，执行卖白夜操作，卖完再检测万象
                        if "han" in opened_items and "baiye" in opened_items:
                            # 找到需要卖出的护符子数组
                            keep_items = ["han", "baiye", "tianen_p", "chelun_p", initial_item]
                            # 找出需要卖出的护符子数组
                            to_sell = [item for item in opened_items if item not in keep_items]
                            sell_amulets(opened_items, to_sell)
                            sell_amulets(opened_items, ["baiye"])
                            move_and_click("最右边护符", sleep_options["开包循环"])
                            han_name, number = find_han()
                            save_log(f"白夜升级邀请函{han_name}")
                            if han_name is None or han_name in ["dashi", "libao", "suo"]:
                                if number == 3:
                                    opened_items.remove("han")
                                    move_and_click("出售")
                                else:
                                    move_and_click("关闭")
                            elif han_name == "wan":
                                return 1
                            else:
                                opened_items.remove("han")
                                opened_items.append(han_name)
                                move_and_click("关闭")
                    elif name in ["tianen_p", "chelun_p"]:
                        # 直接升级的卡，维护已有的数组
                        sell_name = name.replace("_p", "")
                        option_name = f"里面的第{wan_index}个选择"
                        move_and_click(option_name, 0)
                        add_plus(opened_items, sell_name)
                    elif name in ["baiye_p", "mojing_p", "faming_p", "youtong_p", "baozhu_p"]:
                        # 先卖再升级的卡，要先卖上方护符，再选
                        sell_name = name.replace("_p", "")
                        sell_amulets_up(opened_items, [sell_name])
                        option_name = f"里面的第{wan_index}个选择"
                        move_and_click(option_name, sleep_options["最右边护符"])
                        opened_items.append(sell_name)
        if not is_sell:
            is_money2 = check_color("刷新商品", (85, 111, 212), sleep_options["最右边护符"])
            if is_money2:
                move_and_click("刷新商品")
                move_and_click("弹框确认")
            else:
                # 刷新没钱卖卡，根据优先级卖，没卡可卖返回0
                is_sell = sell_one(opened_items, None)
                if not is_sell:
                    return 0
    return 0

def add_plus(opened_items, name):
    """
    此方法用于从 opened_items 中升级指定护符
    :param opened_items: 当前拥有的护符列表
    :param name: 需要升级的指定护符
    """
    for i, item in enumerate(opened_items):
        if item == name:
            opened_items[i] = item + "_p"
    save_log(f"已有护符：{opened_items} 升级{name}")

def sell_amulets(opened_items, to_sell):
    """
    此方法用于从 opened_items 中移除 to_sell 里包含的护符，并输出护符位置
    :param opened_items: 当前拥有的护符列表
    :param to_sell: 需要卖出的护符列表
    :return: 卖出操作后剩余的护符列表
    """
    save_log(f"已有护符：{opened_items} 卖出{to_sell}")
    for item in to_sell:
        while item in opened_items:
            index = opened_items.index(item)
            right_position = len(opened_items) - index
            opened_items.remove(item)
            option_name = f"右{right_position}护符"
            move_and_click(option_name, sleep_options["最右边护符"])
            move_and_click("出售")
    return opened_items

def sell_amulets_up(opened_items, to_sell):
    """
    此方法用于从 opened_items 中移除 to_sell 里包含的护符，并输出护符位置
    :param opened_items: 当前拥有的护符列表
    :param to_sell: 需要卖出的护符列表
    :return: 卖出操作后剩余的护符列表
    """
    save_log(f"已有护符：{opened_items} 上方卖出{to_sell}")
    for item in to_sell:
        while item in opened_items:
            index = opened_items.index(item)
            right_position = index + 1
            opened_items.remove(item)
            option_name = f"上左{right_position}护符"
            option_name2 = f"上左{right_position}护符出售"
            move_and_click(option_name, sleep_options["最右边护符"])
            move_and_click(option_name2, sleep_options["最右边护符"])
    return opened_items

def sell_one(opened_items, button_name1):
    """
    没钱开包或刷新，根据优先级卖掉一个护符
    :return: 是否执行卖出操作
    """
    sell_order = ["youtong", "youtong_p", "faming", "faming_p", "baozhu", "baozhu_p", "mojing", "mojing_p", "han", "baiye", "fenshen", "tianen", "tianen_p"]
    sell_card_name = find_first_card_to_sell(opened_items, sell_order)
    if sell_card_name is None:
        return False
    else:
        if button_name1:
            move_and_click(button_name1)
        sell_amulets(opened_items, [sell_card_name])
        return True

def find_first_card_to_sell(opened_items, sell_order):
    """
    此方法用于从 opened_items 中移除 to_sell 里包含的护符，并输出护符位置
    :param opened_items: 当前拥有的护符列表
    :param sell_order: 卖出优先级
    :return: 需要卖出的护符名称，没有返回None
    """
    for card in sell_order:
        if card in opened_items:
            return card
    return None

def main():
    # 初始等待 2 秒，方便切换到目标界面
    time.sleep(2)

    # 启动键盘监听
    listener = keyboard.Listener(on_press=on_press)
    listener.start()

    # 初始化循环计数器
    loop_count = 1
    while not stop_event.is_set():
        save_log(f"第 {loop_count} 次循环")
        move_and_click("青云之志", 0)
        move_and_click("公子第1个包", 0)
        move_and_click("卡关确认", 0)
        move_and_click("新的开始")
        find_index, find_name = find_fa()
        if find_index > 0:
            save_log(f"开始打牌{find_name}")
            option_name = f"第{find_index}个选择"
            move_and_click(option_name, 0)
            move_and_click("打牌确认", sleep_options["开包循环"])
            time.sleep(sleep_options["打牌确认"])
            if find_name == "chelun" or find_name == "wang":
                exchange_cards_chelun()
                is_win = play_cards_chelun()
            else:
                exchange_cards()
                is_win = play_cards()
            if is_win == 1:
                save_log("开始开包")
                is_wanxiang = find_wanxiang(find_name)
                if is_wanxiang == 1:
                    save_log("找到万象！！！")
                    send_notification_email()
                    press_key('esc')
                    move_and_click("弹框确认")
                    break
        move_and_click("第1个选择", 0)
        move_and_click("返回", sleep_options["返回和放弃"])
        move_and_click("弹框确认")
        move_and_click("放弃按钮", sleep_options["返回和放弃"])
        move_and_click("弹框确认")
        # 循环次数加 1
        loop_count += 1


if __name__ == "__main__":
    # 启动键盘监听
#     listener = keyboard.Listener(on_press=on_press)
#     listener.start()
#     exchange_cards_chelun()
#     play_cards_chelun()
    main()
#     opened_items = ["金闪闪", "发", "she", "墨镜"]
#     to_sell = ["墨镜", "发"]
#     sell_amulets(opened_items, to_sell)
